# Instalación de paquetes (ejecutar solo una vez)
install.packages(c("tidyverse", "plotly", "scales", "lubridate",
                  "corrplot", "gridExtra", "hrbrthemes", "stats"))

# Cargar librerías
library(tidyverse)     # Para manipulación de datos y visualización
library(plotly)        # Para gráficos interactivos
library(scales)        # Para formateo de escalas
library(lubridate)     # Para manejo de fechas
library(corrplot)      # Para matrices de correlación
library(gridExtra)     # Para combinar gráficos
library(hrbrthemes)    # Para temas de visualización
library(stats)         # Para análisis estadístico
if (!requireNamespace("dplyr", quietly = TRUE)) install.packages("dplyr")
if (!requireNamespace("ggplot2", quietly = TRUE)) install.packages("ggplot2")
if (!requireNamespace("plotly", quietly = TRUE)) install.packages("plotly")
if (!requireNamespace("hrbrthemes", quietly = TRUE)) install.packages("hrbrthemes")

library(dplyr)
library(ggplot2)
library(plotly)
library(hrbrthemes)
#Cargar datos
library(readr)
datos <- read_csv("C:/Users/akege/Downloads/enhanced_saas_marketing_data (1).csv")
Rows: 1152 Columns: 38
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr   (3): company, region, product_category
dbl  (34): organic_traffic, direct_traffic, referral_traffic, paid_traffic, ...
date  (1): date

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
View(enhanced_saas_marketing_data_1_)
# Preparación inicial de datos
datos_prep <- datos %>%
  # Convertir fecha a formato Date
  mutate(
    date = as.Date(date),
    month = floor_date(date, "month"),
    # Crear métricas derivadas
    gross_margin = (revenue - costs) / revenue,
    marketing_efficiency = revenue / marketing_spend,
    clv_cac_ratio = customer_lifetime_value / customer_acquisition_cost
  )

# Verificar estructura de datos
str(datos_prep)
tibble [1,152 × 41] (S3: tbl_df/tbl/data.frame)
 $ date                     : Date[1:1152], format: "2022-01-31" "2022-01-31" ...
 $ company                  : chr [1:1152] "SaasCompany1" "SaasCompany1" "SaasCompany1" "SaasCompany1" ...
 $ region                   : chr [1:1152] "North" "North" "North" "South" ...
 $ product_category         : chr [1:1152] "Enterprise" "SMB" "Startup" "Enterprise" ...
 $ organic_traffic          : num [1:1152] 162835 130162 119058 171379 183703 ...
 $ direct_traffic           : num [1:1152] 62183 53651 51618 64307 71783 ...
 $ referral_traffic         : num [1:1152] 31091 26825 25809 32153 35891 ...
 $ paid_traffic             : num [1:1152] 46637 40238 38713 48230 53837 ...
 $ bounce_rate              : num [1:1152] 0.543 0.485 0.49 0.49 0.509 ...
 $ avg_session_duration     : num [1:1152] 217 121 190 269 289 ...
 $ pages_per_session        : num [1:1152] 2.29 4.62 4.75 4.6 3.62 ...
 $ conversion_rate          : num [1:1152] 0.0478 0.0443 0.0421 0.0486 0.0467 ...
 $ email_sends              : num [1:1152] 11543 9195 10509 6031 7723 ...
 $ email_opens              : num [1:1152] 2931 3616 5807 5901 6556 ...
 $ email_clicks             : num [1:1152] 541 621 844 1007 1307 ...
 $ social_posts             : num [1:1152] 42 38 35 46 40 43 41 45 24 22 ...
 $ social_engagement        : num [1:1152] 4028 3242 3473 4405 3405 ...
 $ leads_generated          : num [1:1152] 110 138 118 231 245 126 224 202 171 121 ...
 $ qualified_leads          : num [1:1152] 61 87 103 72 119 149 63 126 86 147 ...
 $ opportunities            : num [1:1152] 45 25 36 42 24 30 49 27 23 58 ...
 $ closed_deals             : num [1:1152] 6 19 23 17 19 12 20 14 9 14 ...
 $ revenue                  : num [1:1152] 59099 125413 147662 83751 84552 ...
 $ costs                    : num [1:1152] 40391 34093 34674 88972 49400 ...
 $ marketing_spend          : num [1:1152] 10403 10689 29984 20573 15177 ...
 $ customer_acquisition_cost: num [1:1152] 160 137 286 153 155 ...
 $ customer_lifetime_value  : num [1:1152] 2331 1060 2388 1951 1224 ...
 $ nps                      : num [1:1152] 50.1 32.5 53.9 76.1 45.5 ...
 $ customer_satisfaction    : num [1:1152] 8.57 9.01 7.99 8.59 8.31 ...
 $ support_tickets          : num [1:1152] 191 82 152 65 102 159 98 133 50 87 ...
 $ resolution_time          : num [1:1152] 13.1 30.2 34.7 20.2 37.7 ...
 $ active_users             : num [1:1152] 1117 3020 1537 3991 4302 ...
 $ feature_adoption_rate    : num [1:1152] 0.509 0.613 0.608 0.628 0.444 ...
 $ churn_rate               : num [1:1152] 0.0405 0.0313 0.0131 0.0495 0.0315 ...
 $ expansion_revenue        : num [1:1152] 8481 9342 11986 13743 11903 ...
 $ gross_margin             : num [1:1152] 0.3166 0.7282 0.7652 -0.0623 0.4157 ...
 $ marketing_roi            : num [1:1152] 4.68 10.73 3.92 3.07 4.57 ...
 $ conversion_to_paid       : num [1:1152] 0.0545 0.1377 0.1949 0.0736 0.0776 ...
 $ email_engagement_rate    : num [1:1152] 0.0469 0.0675 0.0803 0.167 0.1692 ...
 $ month                    : Date[1:1152], format: "2022-01-01" "2022-01-01" ...
 $ marketing_efficiency     : num [1:1152] 5.68 11.73 4.92 4.07 5.57 ...
 $ clv_cac_ratio            : num [1:1152] 14.61 7.76 8.35 12.72 7.91 ...
summary(datos_prep)
      date              company             region          product_category  
 Min.   :2022-01-31   Length:1152        Length:1152        Length:1152       
 1st Qu.:2022-07-23   Class :character   Class :character   Class :character  
 Median :2023-01-15   Mode  :character   Mode  :character   Mode  :character  
 Mean   :2023-01-14                                                           
 3rd Qu.:2023-07-07                                                           
 Max.   :2023-12-31                                                           
 organic_traffic  direct_traffic   referral_traffic  paid_traffic  
 Min.   : 50255   Min.   : 20738   Min.   :10369    Min.   :15554  
 1st Qu.: 97689   1st Qu.: 39133   1st Qu.:19566    1st Qu.:29350  
 Median :138657   Median : 55192   Median :27596    Median :41394  
 Mean   :143115   Mean   : 57175   Mean   :28587    Mean   :42881  
 3rd Qu.:182241   3rd Qu.: 71952   3rd Qu.:35976    3rd Qu.:53964  
 Max.   :287367   Max.   :117133   Max.   :58566    Max.   :87850  
  bounce_rate     avg_session_duration pages_per_session conversion_rate  
 Min.   :0.3003   Min.   :120.0        Min.   :2.002     Min.   :0.01850  
 1st Qu.:0.3726   1st Qu.:162.1        1st Qu.:3.001     1st Qu.:0.02552  
 Median :0.4483   Median :204.4        Median :3.998     Median :0.03170  
 Mean   :0.4488   Mean   :206.5        Mean   :3.999     Mean   :0.03300  
 3rd Qu.:0.5224   3rd Qu.:249.9        3rd Qu.:5.011     3rd Qu.:0.03992  
 Max.   :0.5999   Max.   :299.7        Max.   :5.993     Max.   :0.05442  
  email_sends     email_opens    email_clicks     social_posts  
 Min.   : 5003   Min.   :2003   Min.   : 502.0   Min.   :20.00  
 1st Qu.: 7580   1st Qu.:3525   1st Qu.: 873.8   1st Qu.:27.00  
 Median :10060   Median :4999   Median :1234.0   Median :35.00  
 Mean   : 9997   Mean   :5024   Mean   :1236.0   Mean   :34.88  
 3rd Qu.:12494   3rd Qu.:6505   3rd Qu.:1588.5   3rd Qu.:42.00  
 Max.   :14988   Max.   :7995   Max.   :1998.0   Max.   :49.00  
 social_engagement leads_generated qualified_leads opportunities  
 Min.   :1010      Min.   :100.0   Min.   : 50.0   Min.   :20.00  
 1st Qu.:2013      1st Qu.:151.0   1st Qu.: 76.0   1st Qu.:29.00  
 Median :2972      Median :197.0   Median :101.5   Median :39.00  
 Mean   :2976      Mean   :198.9   Mean   :100.6   Mean   :39.04  
 3rd Qu.:3933      3rd Qu.:246.0   3rd Qu.:125.0   3rd Qu.:49.00  
 Max.   :4999      Max.   :299.0   Max.   :149.0   Max.   :59.00  
  closed_deals     revenue           costs       marketing_spend
 Min.   : 5.0   Min.   : 50076   Min.   :30147   Min.   :10002  
 1st Qu.: 9.0   1st Qu.: 74134   1st Qu.:46084   1st Qu.:14928  
 Median :14.0   Median : 98584   Median :60305   Median :19706  
 Mean   :14.4   Mean   : 99116   Mean   :60734   Mean   :19819  
 3rd Qu.:19.0   3rd Qu.:124962   3rd Qu.:76170   3rd Qu.:24649  
 Max.   :24.0   Max.   :149830   Max.   :89940   Max.   :29995  
 customer_acquisition_cost customer_lifetime_value      nps       
 Min.   :100.1             Min.   :1002            Min.   :30.01  
 1st Qu.:153.0             1st Qu.:1486            1st Qu.:41.67  
 Median :199.4             Median :1991            Median :54.04  
 Mean   :200.1             Mean   :1991            Mean   :54.23  
 3rd Qu.:249.8             3rd Qu.:2512            3rd Qu.:66.50  
 Max.   :299.9             Max.   :3000            Max.   :79.97  
 customer_satisfaction support_tickets  resolution_time   active_users 
 Min.   :7.006         Min.   : 50.00   Min.   : 2.022   Min.   :1005  
 1st Qu.:7.626         1st Qu.: 86.75   1st Qu.:13.670   1st Qu.:2000  
 Median :8.229         Median :123.00   Median :25.354   Median :3034  
 Mean   :8.238         Mean   :124.68   Mean   :25.265   Mean   :3015  
 3rd Qu.:8.872         3rd Qu.:161.25   3rd Qu.:36.720   3rd Qu.:4016  
 Max.   :9.497         Max.   :199.00   Max.   :47.987   Max.   :4999  
 feature_adoption_rate   churn_rate      expansion_revenue  gross_margin    
 Min.   :0.4010        Min.   :0.01006   Min.   : 5009     Min.   :-0.7103  
 1st Qu.:0.4989        1st Qu.:0.01987   1st Qu.: 7519     1st Qu.: 0.1753  
 Median :0.5925        Median :0.03051   Median :10062     Median : 0.3835  
 Mean   :0.5976        Mean   :0.03001   Mean   :10082     Mean   : 0.3273  
 3rd Qu.:0.6994        3rd Qu.:0.03981   3rd Qu.:12754     3rd Qu.: 0.5472  
 Max.   :0.7998        Max.   :0.05000   Max.   :14999     Max.   : 0.7876  
 marketing_roi     conversion_to_paid email_engagement_rate
 Min.   : 0.6938   Min.   :0.01678    Min.   :0.03404      
 1st Qu.: 2.6859   1st Qu.:0.04724    1st Qu.:0.08718      
 Median : 4.0063   Median :0.07238    Median :0.12259      
 Mean   : 4.5028   Mean   :0.07907    Mean   :0.13593      
 3rd Qu.: 5.8268   3rd Qu.:0.10206    3rd Qu.:0.17436      
 Max.   :12.7085   Max.   :0.23301    Max.   :0.37791      
     month            marketing_efficiency clv_cac_ratio   
 Min.   :2022-01-01   Min.   : 1.694       Min.   : 3.409  
 1st Qu.:2022-06-23   1st Qu.: 3.686       1st Qu.: 7.431  
 Median :2022-12-16   Median : 5.006       Median : 9.925  
 Mean   :2022-12-16   Mean   : 5.503       Mean   :10.873  
 3rd Qu.:2023-06-08   3rd Qu.: 6.827       3rd Qu.:13.366  
 Max.   :2023-12-01   Max.   :13.708       Max.   :28.844  
str(datos_prep)
tibble [1,152 × 41] (S3: tbl_df/tbl/data.frame)
 $ date                     : Date[1:1152], format: "2022-01-31" "2022-01-31" ...
 $ company                  : chr [1:1152] "SaasCompany1" "SaasCompany1" "SaasCompany1" "SaasCompany1" ...
 $ region                   : chr [1:1152] "North" "North" "North" "South" ...
 $ product_category         : chr [1:1152] "Enterprise" "SMB" "Startup" "Enterprise" ...
 $ organic_traffic          : num [1:1152] 162835 130162 119058 171379 183703 ...
 $ direct_traffic           : num [1:1152] 62183 53651 51618 64307 71783 ...
 $ referral_traffic         : num [1:1152] 31091 26825 25809 32153 35891 ...
 $ paid_traffic             : num [1:1152] 46637 40238 38713 48230 53837 ...
 $ bounce_rate              : num [1:1152] 0.543 0.485 0.49 0.49 0.509 ...
 $ avg_session_duration     : num [1:1152] 217 121 190 269 289 ...
 $ pages_per_session        : num [1:1152] 2.29 4.62 4.75 4.6 3.62 ...
 $ conversion_rate          : num [1:1152] 0.0478 0.0443 0.0421 0.0486 0.0467 ...
 $ email_sends              : num [1:1152] 11543 9195 10509 6031 7723 ...
 $ email_opens              : num [1:1152] 2931 3616 5807 5901 6556 ...
 $ email_clicks             : num [1:1152] 541 621 844 1007 1307 ...
 $ social_posts             : num [1:1152] 42 38 35 46 40 43 41 45 24 22 ...
 $ social_engagement        : num [1:1152] 4028 3242 3473 4405 3405 ...
 $ leads_generated          : num [1:1152] 110 138 118 231 245 126 224 202 171 121 ...
 $ qualified_leads          : num [1:1152] 61 87 103 72 119 149 63 126 86 147 ...
 $ opportunities            : num [1:1152] 45 25 36 42 24 30 49 27 23 58 ...
 $ closed_deals             : num [1:1152] 6 19 23 17 19 12 20 14 9 14 ...
 $ revenue                  : num [1:1152] 59099 125413 147662 83751 84552 ...
 $ costs                    : num [1:1152] 40391 34093 34674 88972 49400 ...
 $ marketing_spend          : num [1:1152] 10403 10689 29984 20573 15177 ...
 $ customer_acquisition_cost: num [1:1152] 160 137 286 153 155 ...
 $ customer_lifetime_value  : num [1:1152] 2331 1060 2388 1951 1224 ...
 $ nps                      : num [1:1152] 50.1 32.5 53.9 76.1 45.5 ...
 $ customer_satisfaction    : num [1:1152] 8.57 9.01 7.99 8.59 8.31 ...
 $ support_tickets          : num [1:1152] 191 82 152 65 102 159 98 133 50 87 ...
 $ resolution_time          : num [1:1152] 13.1 30.2 34.7 20.2 37.7 ...
 $ active_users             : num [1:1152] 1117 3020 1537 3991 4302 ...
 $ feature_adoption_rate    : num [1:1152] 0.509 0.613 0.608 0.628 0.444 ...
 $ churn_rate               : num [1:1152] 0.0405 0.0313 0.0131 0.0495 0.0315 ...
 $ expansion_revenue        : num [1:1152] 8481 9342 11986 13743 11903 ...
 $ gross_margin             : num [1:1152] 0.3166 0.7282 0.7652 -0.0623 0.4157 ...
 $ marketing_roi            : num [1:1152] 4.68 10.73 3.92 3.07 4.57 ...
 $ conversion_to_paid       : num [1:1152] 0.0545 0.1377 0.1949 0.0736 0.0776 ...
 $ email_engagement_rate    : num [1:1152] 0.0469 0.0675 0.0803 0.167 0.1692 ...
 $ month                    : Date[1:1152], format: "2022-01-01" "2022-01-01" ...
 $ marketing_efficiency     : num [1:1152] 5.68 11.73 4.92 4.07 5.57 ...
 $ clv_cac_ratio            : num [1:1152] 14.61 7.76 8.35 12.72 7.91 ...
# Convertir `date` a formato Date si no lo está
datos <- datos %>%
  mutate(date = as.Date(date))

# Confirma el tipo de datos
str(datos)
tibble [1,152 × 38] (S3: tbl_df/tbl/data.frame)
 $ date                     : Date[1:1152], format: "2022-01-31" "2022-01-31" ...
 $ company                  : chr [1:1152] "SaasCompany1" "SaasCompany1" "SaasCompany1" "SaasCompany1" ...
 $ region                   : chr [1:1152] "North" "North" "North" "South" ...
 $ product_category         : chr [1:1152] "Enterprise" "SMB" "Startup" "Enterprise" ...
 $ organic_traffic          : num [1:1152] 162835 130162 119058 171379 183703 ...
 $ direct_traffic           : num [1:1152] 62183 53651 51618 64307 71783 ...
 $ referral_traffic         : num [1:1152] 31091 26825 25809 32153 35891 ...
 $ paid_traffic             : num [1:1152] 46637 40238 38713 48230 53837 ...
 $ bounce_rate              : num [1:1152] 0.543 0.485 0.49 0.49 0.509 ...
 $ avg_session_duration     : num [1:1152] 217 121 190 269 289 ...
 $ pages_per_session        : num [1:1152] 2.29 4.62 4.75 4.6 3.62 ...
 $ conversion_rate          : num [1:1152] 0.0478 0.0443 0.0421 0.0486 0.0467 ...
 $ email_sends              : num [1:1152] 11543 9195 10509 6031 7723 ...
 $ email_opens              : num [1:1152] 2931 3616 5807 5901 6556 ...
 $ email_clicks             : num [1:1152] 541 621 844 1007 1307 ...
 $ social_posts             : num [1:1152] 42 38 35 46 40 43 41 45 24 22 ...
 $ social_engagement        : num [1:1152] 4028 3242 3473 4405 3405 ...
 $ leads_generated          : num [1:1152] 110 138 118 231 245 126 224 202 171 121 ...
 $ qualified_leads          : num [1:1152] 61 87 103 72 119 149 63 126 86 147 ...
 $ opportunities            : num [1:1152] 45 25 36 42 24 30 49 27 23 58 ...
 $ closed_deals             : num [1:1152] 6 19 23 17 19 12 20 14 9 14 ...
 $ revenue                  : num [1:1152] 59099 125413 147662 83751 84552 ...
 $ costs                    : num [1:1152] 40391 34093 34674 88972 49400 ...
 $ marketing_spend          : num [1:1152] 10403 10689 29984 20573 15177 ...
 $ customer_acquisition_cost: num [1:1152] 160 137 286 153 155 ...
 $ customer_lifetime_value  : num [1:1152] 2331 1060 2388 1951 1224 ...
 $ nps                      : num [1:1152] 50.1 32.5 53.9 76.1 45.5 ...
 $ customer_satisfaction    : num [1:1152] 8.57 9.01 7.99 8.59 8.31 ...
 $ support_tickets          : num [1:1152] 191 82 152 65 102 159 98 133 50 87 ...
 $ resolution_time          : num [1:1152] 13.1 30.2 34.7 20.2 37.7 ...
 $ active_users             : num [1:1152] 1117 3020 1537 3991 4302 ...
 $ feature_adoption_rate    : num [1:1152] 0.509 0.613 0.608 0.628 0.444 ...
 $ churn_rate               : num [1:1152] 0.0405 0.0313 0.0131 0.0495 0.0315 ...
 $ expansion_revenue        : num [1:1152] 8481 9342 11986 13743 11903 ...
 $ gross_margin             : num [1:1152] 0.3166 0.7282 0.7652 -0.0623 0.4157 ...
 $ marketing_roi            : num [1:1152] 4.68 10.73 3.92 3.07 4.57 ...
 $ conversion_to_paid       : num [1:1152] 0.0545 0.1377 0.1949 0.0736 0.0776 ...
 $ email_engagement_rate    : num [1:1152] 0.0469 0.0675 0.0803 0.167 0.1692 ...
crear_tendencias <- function(datos, metrica, titulo) {
  # Validar que las columnas necesarias existen
  validar_columnas(datos, c("date", "company", metrica))
  
  # Convertir `date` a formato Date
  datos <- datos %>%
    mutate(date = as.Date(date))
  
  # Resumir datos
  datos_resumidos <- datos %>%
    group_by(date, company) %>%
    summarise(valor = mean(!!sym(metrica), na.rm = TRUE), .groups = 'drop')
  
  # Verifica que hay datos
  if (nrow(datos_resumidos) == 0) {
    stop("No hay datos disponibles para la métrica especificada.")
  }
  
  # Crear el gráfico
  grafico <- datos_resumidos %>%
    ggplot(aes(x = date, y = valor, color = company)) +
    geom_line(size = 1) +
    geom_point(size = 2) +
    theme_ipsum() +
    labs(
      title = titulo,
      x = "Fecha",
      y = metrica
    ) +
    theme(legend.position = "bottom")
  
  # Convertir a gráfico interactivo
  return(ggplotly(grafico))
}

# Ejemplo de uso
crear_tendencias(datos_prep, "revenue", "Tendencia de Ingresos")
NA
# Función para análisis de distribución
analizar_distribucion <- function(datos, variable) {
  # Histograma
  hist <- ggplot(datos, aes(x = !!sym(variable), fill = company)) +
    geom_histogram(alpha = 0.6, bins = 30) +
    facet_wrap(~company, scales = "free") +
    theme_minimal() +
    labs(title = paste("Distribución de", variable))

  # Box plot
  box <- ggplot(datos, aes(x = company, y = !!sym(variable), fill = company)) +
    geom_boxplot() +
    theme_minimal() +
    labs(title = paste("Box Plot de", variable)) +
    theme(axis.text.x = element_text(angle = 45))

  # Combinar gráficos
  grid.arrange(hist, box, ncol = 1)
}

# Analizar distribuciones de métricas clave
analizar_distribucion(datos_prep, "revenue")

analizar_distribucion(datos_prep, "customer_lifetime_value")

library(dplyr)
library(purrr)

# Función para análisis estadístico por empresa
analisis_estadistico <- function(datos) {
  # Asegúrate de que los datos estén agrupados correctamente
  resumen <- datos %>%
    group_by(company) %>%
    summarise(
      # Métricas financieras
      revenue_mean = mean(revenue, na.rm = TRUE),
      revenue_sd = sd(revenue, na.rm = TRUE),
      margin_mean = mean(gross_margin, na.rm = TRUE),
      
      # Métricas de cliente
      cac_mean = mean(customer_acquisition_cost, na.rm = TRUE),
      clv_mean = mean(customer_lifetime_value, na.rm = TRUE),
      clv_cac_ratio = mean(clv_cac_ratio, na.rm = TRUE),

      # Métricas de engagement
      satisfaction_mean = mean(customer_satisfaction, na.rm = TRUE),
      churn_rate_mean = mean(churn_rate, na.rm = TRUE),
      
      # Número de observaciones
      n = n()
    ) %>%
    # Agregar prueba de normalidad (por separado debido a la naturaleza de shapiro.test)
    mutate(
      revenue_normality = map_dbl(split(datos$revenue, datos$company), 
                                  ~ if (length(na.omit(.x)) > 3) shapiro.test(.x)$p.value else NA_real_)
    )
  
  return(resumen)
}

# Ejecutar análisis estadístico
resumen_estadistico <- analisis_estadistico(datos_prep)

# Mostrar resultados
print(resumen_estadistico)
library(corrplot)
library(dplyr)

analizar_correlaciones <- function(datos, metodo = "pearson", variables = NULL) {
  # Seleccionar métricas numéricas
  metricas_numericas <- datos %>%
    select_if(is.numeric)
  
  # Si se proporcionan variables, seleccionarlas
  if (!is.null(variables)) {
    metricas_numericas <- metricas_numericas %>%
      select(all_of(variables))
  }

  # Calcular matriz de correlaciones
  correlaciones <- cor(metricas_numericas, use = "complete.obs", method = metodo)

  # Renombrar columnas con abreviaturas
  colnames(correlaciones) <- abbreviate(colnames(correlaciones), minlength = 6)
  rownames(correlaciones) <- abbreviate(rownames(correlaciones), minlength = 6)

  # Ajustar tamaño del gráfico
  par(mar = c(0, 0, 2, 0)) # Márgenes más pequeños
  corrplot(correlaciones,
           method = "color",         # Estilo de color
           type = "upper",           # Mostrar solo la parte superior
           addCoef.col = "black",    # Mostrar coeficientes en negro
           number.cex = 0.7,         # Tamaño de coeficientes
           tl.cex = 0.8,             # Tamaño de etiquetas
           tl.srt = 45,              # Rotar etiquetas 45 grados
           title = "Matriz de Correlaciones")
}

# Seleccionar un subconjunto de variables para claridad
variables_interes <- c("organic_traffic", "direct_traffic", "referral_traffic", 
                       "paid_traffic", "bounce_rate", "conversion_rate", 
                       "revenue", "marketing_spend", "customer_satisfaction", 
                       "churn_rate")

# Ejecutar análisis de correlaciones con variables seleccionadas
analizar_correlaciones(datos_prep, metodo = "spearman", variables = variables_interes)

library(corrplot)

analizar_correlaciones <- function(datos, metodo = "pearson") {
  # Seleccionar métricas numéricas
  metricas_numericas <- datos %>%
    select_if(is.numeric)  # Seleccionar solo columnas numéricas

  # Calcular matriz de correlaciones
  correlaciones <- cor(metricas_numericas, use = "complete.obs", method = metodo)

  # Crear visualización de la matriz de correlaciones con ajustes
  corrplot(correlaciones,
           method = "color",         # Estilo de color para las correlaciones
           type = "upper",           # Mostrar solo la mitad superior
           addCoef.col = "black",    # Mostrar valores numéricos en negro
           number.cex = 0.6,         # Tamaño de los coeficientes numéricos
           tl.cex = 0.6,             # Tamaño de las etiquetas de texto
           tl.col = "blue",          # Color de las etiquetas de texto
           tl.srt = 45,              # Rotar etiquetas 45 grados
           title = "Matriz de Correlaciones", 
           mar = c(0, 0, 2, 0))      # Márgenes del gráfico
}

# Ejecutar análisis de correlaciones
analizar_correlaciones(datos_prep, metodo = "spearman")

NA
NA
library(ggplot2)
library(dplyr)
library(plotly)

analisis_roi <- function(datos) {
  # Agrupar y calcular métricas
  roi_plot <- datos %>%
    group_by(company, month) %>%
    summarise(
      marketing_roi = mean(marketing_roi, na.rm = TRUE),
      marketing_spend = mean(marketing_spend, na.rm = TRUE),
      .groups = 'drop'  # Evitar mensajes sobre agrupamiento
    ) %>%
    # Crear gráfico
    ggplot(aes(x = marketing_spend, y = marketing_roi, color = company)) +
    geom_point(size = 3, alpha = 0.6) +       # Puntos de datos
    geom_smooth(method = "lm", se = FALSE) + # Línea de tendencia
    theme_minimal() +
    labs(
      title = "ROI vs Inversión en Marketing",
      x = "Inversión en Marketing",
      y = "ROI"
    ) +
    theme(
      legend.position = "bottom",  # Leyenda en la parte inferior
      plot.title = element_text(size = 16, face = "bold"), 
      axis.title = element_text(size = 12)
    )

  # Convertir gráfico a interactivo con plotly
  return(ggplotly(roi_plot))
}

# Visualizar análisis de ROI
grafico_roi <- analisis_roi(datos_prep)
`geom_smooth()` using formula = 'y ~ x'
# Mostrar gráfico interactivo
grafico_roi
NA
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7cn0NCiMgSW5zdGFsYWNpw7NuIGRlIHBhcXVldGVzIChlamVjdXRhciBzb2xvIHVuYSB2ZXopDQppbnN0YWxsLnBhY2thZ2VzKGMoInRpZHl2ZXJzZSIsICJwbG90bHkiLCAic2NhbGVzIiwgImx1YnJpZGF0ZSIsDQogICAgICAgICAgICAgICAgICAiY29ycnBsb3QiLCAiZ3JpZEV4dHJhIiwgImhyYnJ0aGVtZXMiLCAic3RhdHMiKSkNCg0KIyBDYXJnYXIgbGlicmVyw61hcw0KbGlicmFyeSh0aWR5dmVyc2UpICAgICAjIFBhcmEgbWFuaXB1bGFjacOzbiBkZSBkYXRvcyB5IHZpc3VhbGl6YWNpw7NuDQpsaWJyYXJ5KHBsb3RseSkgICAgICAgICMgUGFyYSBncsOhZmljb3MgaW50ZXJhY3Rpdm9zDQpsaWJyYXJ5KHNjYWxlcykgICAgICAgICMgUGFyYSBmb3JtYXRlbyBkZSBlc2NhbGFzDQpsaWJyYXJ5KGx1YnJpZGF0ZSkgICAgICMgUGFyYSBtYW5lam8gZGUgZmVjaGFzDQpsaWJyYXJ5KGNvcnJwbG90KSAgICAgICMgUGFyYSBtYXRyaWNlcyBkZSBjb3JyZWxhY2nDs24NCmxpYnJhcnkoZ3JpZEV4dHJhKSAgICAgIyBQYXJhIGNvbWJpbmFyIGdyw6FmaWNvcw0KbGlicmFyeShocmJydGhlbWVzKSAgICAjIFBhcmEgdGVtYXMgZGUgdmlzdWFsaXphY2nDs24NCmxpYnJhcnkoc3RhdHMpICAgICAgICAgIyBQYXJhIGFuw6FsaXNpcyBlc3RhZMOtc3RpY28NCmBgYA0KDQpgYGB7cn0NCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiZHBseXIiLCBxdWlldGx5ID0gVFJVRSkpIGluc3RhbGwucGFja2FnZXMoImRwbHlyIikNCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiZ2dwbG90MiIsIHF1aWV0bHkgPSBUUlVFKSkgaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpDQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoInBsb3RseSIsIHF1aWV0bHkgPSBUUlVFKSkgaW5zdGFsbC5wYWNrYWdlcygicGxvdGx5IikNCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiaHJicnRoZW1lcyIsIHF1aWV0bHkgPSBUUlVFKSkgaW5zdGFsbC5wYWNrYWdlcygiaHJicnRoZW1lcyIpDQoNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoaHJicnRoZW1lcykNCg0KYGBgDQoNCmBgYHtyfQ0KI0NhcmdhciBkYXRvcw0KbGlicmFyeShyZWFkcikNCmRhdG9zIDwtIHJlYWRfY3N2KCJDOi9Vc2Vycy9ha2VnZS9Eb3dubG9hZHMvZW5oYW5jZWRfc2Fhc19tYXJrZXRpbmdfZGF0YSAoMSkuY3N2IikNClZpZXcoZW5oYW5jZWRfc2Fhc19tYXJrZXRpbmdfZGF0YV8xXykNCmBgYA0KDQpgYGB7cn0NCiMgUHJlcGFyYWNpw7NuIGluaWNpYWwgZGUgZGF0b3MNCmRhdG9zX3ByZXAgPC0gZGF0b3MgJT4lDQogICMgQ29udmVydGlyIGZlY2hhIGEgZm9ybWF0byBEYXRlDQogIG11dGF0ZSgNCiAgICBkYXRlID0gYXMuRGF0ZShkYXRlKSwNCiAgICBtb250aCA9IGZsb29yX2RhdGUoZGF0ZSwgIm1vbnRoIiksDQogICAgIyBDcmVhciBtw6l0cmljYXMgZGVyaXZhZGFzDQogICAgZ3Jvc3NfbWFyZ2luID0gKHJldmVudWUgLSBjb3N0cykgLyByZXZlbnVlLA0KICAgIG1hcmtldGluZ19lZmZpY2llbmN5ID0gcmV2ZW51ZSAvIG1hcmtldGluZ19zcGVuZCwNCiAgICBjbHZfY2FjX3JhdGlvID0gY3VzdG9tZXJfbGlmZXRpbWVfdmFsdWUgLyBjdXN0b21lcl9hY3F1aXNpdGlvbl9jb3N0DQogICkNCg0KIyBWZXJpZmljYXIgZXN0cnVjdHVyYSBkZSBkYXRvcw0Kc3RyKGRhdG9zX3ByZXApDQpzdW1tYXJ5KGRhdG9zX3ByZXApDQoNCmBgYA0KDQpgYGB7cn0NCnN0cihkYXRvc19wcmVwKQ0KYGBgDQoNCmBgYHtyfQ0KIyBDb252ZXJ0aXIgYGRhdGVgIGEgZm9ybWF0byBEYXRlIHNpIG5vIGxvIGVzdMOhDQpkYXRvcyA8LSBkYXRvcyAlPiUNCiAgbXV0YXRlKGRhdGUgPSBhcy5EYXRlKGRhdGUpKQ0KDQojIENvbmZpcm1hIGVsIHRpcG8gZGUgZGF0b3MNCnN0cihkYXRvcykNCg0KYGBgDQoNCmBgYHtyfQ0KY3JlYXJfdGVuZGVuY2lhcyA8LSBmdW5jdGlvbihkYXRvcywgbWV0cmljYSwgdGl0dWxvKSB7DQogICMgVmFsaWRhciBxdWUgbGFzIGNvbHVtbmFzIG5lY2VzYXJpYXMgZXhpc3Rlbg0KICB2YWxpZGFyX2NvbHVtbmFzKGRhdG9zLCBjKCJkYXRlIiwgImNvbXBhbnkiLCBtZXRyaWNhKSkNCiAgDQogICMgQ29udmVydGlyIGBkYXRlYCBhIGZvcm1hdG8gRGF0ZQ0KICBkYXRvcyA8LSBkYXRvcyAlPiUNCiAgICBtdXRhdGUoZGF0ZSA9IGFzLkRhdGUoZGF0ZSkpDQogIA0KICAjIFJlc3VtaXIgZGF0b3MNCiAgZGF0b3NfcmVzdW1pZG9zIDwtIGRhdG9zICU+JQ0KICAgIGdyb3VwX2J5KGRhdGUsIGNvbXBhbnkpICU+JQ0KICAgIHN1bW1hcmlzZSh2YWxvciA9IG1lYW4oISFzeW0obWV0cmljYSksIG5hLnJtID0gVFJVRSksIC5ncm91cHMgPSAnZHJvcCcpDQogIA0KICAjIFZlcmlmaWNhIHF1ZSBoYXkgZGF0b3MNCiAgaWYgKG5yb3coZGF0b3NfcmVzdW1pZG9zKSA9PSAwKSB7DQogICAgc3RvcCgiTm8gaGF5IGRhdG9zIGRpc3BvbmlibGVzIHBhcmEgbGEgbcOpdHJpY2EgZXNwZWNpZmljYWRhLiIpDQogIH0NCiAgDQogICMgQ3JlYXIgZWwgZ3LDoWZpY28NCiAgZ3JhZmljbyA8LSBkYXRvc19yZXN1bWlkb3MgJT4lDQogICAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IHZhbG9yLCBjb2xvciA9IGNvbXBhbnkpKSArDQogICAgZ2VvbV9saW5lKHNpemUgPSAxKSArDQogICAgZ2VvbV9wb2ludChzaXplID0gMikgKw0KICAgIHRoZW1lX2lwc3VtKCkgKw0KICAgIGxhYnMoDQogICAgICB0aXRsZSA9IHRpdHVsbywNCiAgICAgIHggPSAiRmVjaGEiLA0KICAgICAgeSA9IG1ldHJpY2ENCiAgICApICsNCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikNCiAgDQogICMgQ29udmVydGlyIGEgZ3LDoWZpY28gaW50ZXJhY3Rpdm8NCiAgcmV0dXJuKGdncGxvdGx5KGdyYWZpY28pKQ0KfQ0KDQojIEVqZW1wbG8gZGUgdXNvDQpjcmVhcl90ZW5kZW5jaWFzKGRhdG9zX3ByZXAsICJyZXZlbnVlIiwgIlRlbmRlbmNpYSBkZSBJbmdyZXNvcyIpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KIyBGdW5jacOzbiBwYXJhIGFuw6FsaXNpcyBkZSBkaXN0cmlidWNpw7NuDQphbmFsaXphcl9kaXN0cmlidWNpb24gPC0gZnVuY3Rpb24oZGF0b3MsIHZhcmlhYmxlKSB7DQogICMgSGlzdG9ncmFtYQ0KICBoaXN0IDwtIGdncGxvdChkYXRvcywgYWVzKHggPSAhIXN5bSh2YXJpYWJsZSksIGZpbGwgPSBjb21wYW55KSkgKw0KICAgIGdlb21faGlzdG9ncmFtKGFscGhhID0gMC42LCBiaW5zID0gMzApICsNCiAgICBmYWNldF93cmFwKH5jb21wYW55LCBzY2FsZXMgPSAiZnJlZSIpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGxhYnModGl0bGUgPSBwYXN0ZSgiRGlzdHJpYnVjacOzbiBkZSIsIHZhcmlhYmxlKSkNCg0KICAjIEJveCBwbG90DQogIGJveCA8LSBnZ3Bsb3QoZGF0b3MsIGFlcyh4ID0gY29tcGFueSwgeSA9ICEhc3ltKHZhcmlhYmxlKSwgZmlsbCA9IGNvbXBhbnkpKSArDQogICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgbGFicyh0aXRsZSA9IHBhc3RlKCJCb3ggUGxvdCBkZSIsIHZhcmlhYmxlKSkgKw0KICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUpKQ0KDQogICMgQ29tYmluYXIgZ3LDoWZpY29zDQogIGdyaWQuYXJyYW5nZShoaXN0LCBib3gsIG5jb2wgPSAxKQ0KfQ0KDQojIEFuYWxpemFyIGRpc3RyaWJ1Y2lvbmVzIGRlIG3DqXRyaWNhcyBjbGF2ZQ0KYW5hbGl6YXJfZGlzdHJpYnVjaW9uKGRhdG9zX3ByZXAsICJyZXZlbnVlIikNCmFuYWxpemFyX2Rpc3RyaWJ1Y2lvbihkYXRvc19wcmVwLCAiY3VzdG9tZXJfbGlmZXRpbWVfdmFsdWUiKQ0KDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShwdXJycikNCg0KIyBGdW5jacOzbiBwYXJhIGFuw6FsaXNpcyBlc3RhZMOtc3RpY28gcG9yIGVtcHJlc2ENCmFuYWxpc2lzX2VzdGFkaXN0aWNvIDwtIGZ1bmN0aW9uKGRhdG9zKSB7DQogICMgQXNlZ8O6cmF0ZSBkZSBxdWUgbG9zIGRhdG9zIGVzdMOpbiBhZ3J1cGFkb3MgY29ycmVjdGFtZW50ZQ0KICByZXN1bWVuIDwtIGRhdG9zICU+JQ0KICAgIGdyb3VwX2J5KGNvbXBhbnkpICU+JQ0KICAgIHN1bW1hcmlzZSgNCiAgICAgICMgTcOpdHJpY2FzIGZpbmFuY2llcmFzDQogICAgICByZXZlbnVlX21lYW4gPSBtZWFuKHJldmVudWUsIG5hLnJtID0gVFJVRSksDQogICAgICByZXZlbnVlX3NkID0gc2QocmV2ZW51ZSwgbmEucm0gPSBUUlVFKSwNCiAgICAgIG1hcmdpbl9tZWFuID0gbWVhbihncm9zc19tYXJnaW4sIG5hLnJtID0gVFJVRSksDQogICAgICANCiAgICAgICMgTcOpdHJpY2FzIGRlIGNsaWVudGUNCiAgICAgIGNhY19tZWFuID0gbWVhbihjdXN0b21lcl9hY3F1aXNpdGlvbl9jb3N0LCBuYS5ybSA9IFRSVUUpLA0KICAgICAgY2x2X21lYW4gPSBtZWFuKGN1c3RvbWVyX2xpZmV0aW1lX3ZhbHVlLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgY2x2X2NhY19yYXRpbyA9IG1lYW4oY2x2X2NhY19yYXRpbywgbmEucm0gPSBUUlVFKSwNCg0KICAgICAgIyBNw6l0cmljYXMgZGUgZW5nYWdlbWVudA0KICAgICAgc2F0aXNmYWN0aW9uX21lYW4gPSBtZWFuKGN1c3RvbWVyX3NhdGlzZmFjdGlvbiwgbmEucm0gPSBUUlVFKSwNCiAgICAgIGNodXJuX3JhdGVfbWVhbiA9IG1lYW4oY2h1cm5fcmF0ZSwgbmEucm0gPSBUUlVFKSwNCiAgICAgIA0KICAgICAgIyBOw7ptZXJvIGRlIG9ic2VydmFjaW9uZXMNCiAgICAgIG4gPSBuKCkNCiAgICApICU+JQ0KICAgICMgQWdyZWdhciBwcnVlYmEgZGUgbm9ybWFsaWRhZCAocG9yIHNlcGFyYWRvIGRlYmlkbyBhIGxhIG5hdHVyYWxlemEgZGUgc2hhcGlyby50ZXN0KQ0KICAgIG11dGF0ZSgNCiAgICAgIHJldmVudWVfbm9ybWFsaXR5ID0gbWFwX2RibChzcGxpdChkYXRvcyRyZXZlbnVlLCBkYXRvcyRjb21wYW55KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfiBpZiAobGVuZ3RoKG5hLm9taXQoLngpKSA+IDMpIHNoYXBpcm8udGVzdCgueCkkcC52YWx1ZSBlbHNlIE5BX3JlYWxfKQ0KICAgICkNCiAgDQogIHJldHVybihyZXN1bWVuKQ0KfQ0KDQojIEVqZWN1dGFyIGFuw6FsaXNpcyBlc3RhZMOtc3RpY28NCnJlc3VtZW5fZXN0YWRpc3RpY28gPC0gYW5hbGlzaXNfZXN0YWRpc3RpY28oZGF0b3NfcHJlcCkNCg0KIyBNb3N0cmFyIHJlc3VsdGFkb3MNCnByaW50KHJlc3VtZW5fZXN0YWRpc3RpY28pDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KGNvcnJwbG90KQ0KbGlicmFyeShkcGx5cikNCg0KYW5hbGl6YXJfY29ycmVsYWNpb25lcyA8LSBmdW5jdGlvbihkYXRvcywgbWV0b2RvID0gInBlYXJzb24iLCB2YXJpYWJsZXMgPSBOVUxMKSB7DQogICMgU2VsZWNjaW9uYXIgbcOpdHJpY2FzIG51bcOpcmljYXMNCiAgbWV0cmljYXNfbnVtZXJpY2FzIDwtIGRhdG9zICU+JQ0KICAgIHNlbGVjdF9pZihpcy5udW1lcmljKQ0KICANCiAgIyBTaSBzZSBwcm9wb3JjaW9uYW4gdmFyaWFibGVzLCBzZWxlY2Npb25hcmxhcw0KICBpZiAoIWlzLm51bGwodmFyaWFibGVzKSkgew0KICAgIG1ldHJpY2FzX251bWVyaWNhcyA8LSBtZXRyaWNhc19udW1lcmljYXMgJT4lDQogICAgICBzZWxlY3QoYWxsX29mKHZhcmlhYmxlcykpDQogIH0NCg0KICAjIENhbGN1bGFyIG1hdHJpeiBkZSBjb3JyZWxhY2lvbmVzDQogIGNvcnJlbGFjaW9uZXMgPC0gY29yKG1ldHJpY2FzX251bWVyaWNhcywgdXNlID0gImNvbXBsZXRlLm9icyIsIG1ldGhvZCA9IG1ldG9kbykNCg0KICAjIFJlbm9tYnJhciBjb2x1bW5hcyBjb24gYWJyZXZpYXR1cmFzDQogIGNvbG5hbWVzKGNvcnJlbGFjaW9uZXMpIDwtIGFiYnJldmlhdGUoY29sbmFtZXMoY29ycmVsYWNpb25lcyksIG1pbmxlbmd0aCA9IDYpDQogIHJvd25hbWVzKGNvcnJlbGFjaW9uZXMpIDwtIGFiYnJldmlhdGUocm93bmFtZXMoY29ycmVsYWNpb25lcyksIG1pbmxlbmd0aCA9IDYpDQoNCiAgIyBBanVzdGFyIHRhbWHDsW8gZGVsIGdyw6FmaWNvDQogIHBhcihtYXIgPSBjKDAsIDAsIDIsIDApKSAjIE3DoXJnZW5lcyBtw6FzIHBlcXVlw7Fvcw0KICBjb3JycGxvdChjb3JyZWxhY2lvbmVzLA0KICAgICAgICAgICBtZXRob2QgPSAiY29sb3IiLCAgICAgICAgICMgRXN0aWxvIGRlIGNvbG9yDQogICAgICAgICAgIHR5cGUgPSAidXBwZXIiLCAgICAgICAgICAgIyBNb3N0cmFyIHNvbG8gbGEgcGFydGUgc3VwZXJpb3INCiAgICAgICAgICAgYWRkQ29lZi5jb2wgPSAiYmxhY2siLCAgICAjIE1vc3RyYXIgY29lZmljaWVudGVzIGVuIG5lZ3JvDQogICAgICAgICAgIG51bWJlci5jZXggPSAwLjcsICAgICAgICAgIyBUYW1hw7FvIGRlIGNvZWZpY2llbnRlcw0KICAgICAgICAgICB0bC5jZXggPSAwLjgsICAgICAgICAgICAgICMgVGFtYcOxbyBkZSBldGlxdWV0YXMNCiAgICAgICAgICAgdGwuc3J0ID0gNDUsICAgICAgICAgICAgICAjIFJvdGFyIGV0aXF1ZXRhcyA0NSBncmFkb3MNCiAgICAgICAgICAgdGl0bGUgPSAiTWF0cml6IGRlIENvcnJlbGFjaW9uZXMiKQ0KfQ0KDQojIFNlbGVjY2lvbmFyIHVuIHN1YmNvbmp1bnRvIGRlIHZhcmlhYmxlcyBwYXJhIGNsYXJpZGFkDQp2YXJpYWJsZXNfaW50ZXJlcyA8LSBjKCJvcmdhbmljX3RyYWZmaWMiLCAiZGlyZWN0X3RyYWZmaWMiLCAicmVmZXJyYWxfdHJhZmZpYyIsIA0KICAgICAgICAgICAgICAgICAgICAgICAicGFpZF90cmFmZmljIiwgImJvdW5jZV9yYXRlIiwgImNvbnZlcnNpb25fcmF0ZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAicmV2ZW51ZSIsICJtYXJrZXRpbmdfc3BlbmQiLCAiY3VzdG9tZXJfc2F0aXNmYWN0aW9uIiwgDQogICAgICAgICAgICAgICAgICAgICAgICJjaHVybl9yYXRlIikNCg0KIyBFamVjdXRhciBhbsOhbGlzaXMgZGUgY29ycmVsYWNpb25lcyBjb24gdmFyaWFibGVzIHNlbGVjY2lvbmFkYXMNCmFuYWxpemFyX2NvcnJlbGFjaW9uZXMoZGF0b3NfcHJlcCwgbWV0b2RvID0gInNwZWFybWFuIiwgdmFyaWFibGVzID0gdmFyaWFibGVzX2ludGVyZXMpDQoNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkoY29ycnBsb3QpDQoNCmFuYWxpemFyX2NvcnJlbGFjaW9uZXMgPC0gZnVuY3Rpb24oZGF0b3MsIG1ldG9kbyA9ICJwZWFyc29uIikgew0KICAjIFNlbGVjY2lvbmFyIG3DqXRyaWNhcyBudW3DqXJpY2FzDQogIG1ldHJpY2FzX251bWVyaWNhcyA8LSBkYXRvcyAlPiUNCiAgICBzZWxlY3RfaWYoaXMubnVtZXJpYykgICMgU2VsZWNjaW9uYXIgc29sbyBjb2x1bW5hcyBudW3DqXJpY2FzDQoNCiAgIyBDYWxjdWxhciBtYXRyaXogZGUgY29ycmVsYWNpb25lcw0KICBjb3JyZWxhY2lvbmVzIDwtIGNvcihtZXRyaWNhc19udW1lcmljYXMsIHVzZSA9ICJjb21wbGV0ZS5vYnMiLCBtZXRob2QgPSBtZXRvZG8pDQoNCiAgIyBDcmVhciB2aXN1YWxpemFjacOzbiBkZSBsYSBtYXRyaXogZGUgY29ycmVsYWNpb25lcyBjb24gYWp1c3Rlcw0KICBjb3JycGxvdChjb3JyZWxhY2lvbmVzLA0KICAgICAgICAgICBtZXRob2QgPSAiY29sb3IiLCAgICAgICAgICMgRXN0aWxvIGRlIGNvbG9yIHBhcmEgbGFzIGNvcnJlbGFjaW9uZXMNCiAgICAgICAgICAgdHlwZSA9ICJ1cHBlciIsICAgICAgICAgICAjIE1vc3RyYXIgc29sbyBsYSBtaXRhZCBzdXBlcmlvcg0KICAgICAgICAgICBhZGRDb2VmLmNvbCA9ICJibGFjayIsICAgICMgTW9zdHJhciB2YWxvcmVzIG51bcOpcmljb3MgZW4gbmVncm8NCiAgICAgICAgICAgbnVtYmVyLmNleCA9IDAuNiwgICAgICAgICAjIFRhbWHDsW8gZGUgbG9zIGNvZWZpY2llbnRlcyBudW3DqXJpY29zDQogICAgICAgICAgIHRsLmNleCA9IDAuNiwgICAgICAgICAgICAgIyBUYW1hw7FvIGRlIGxhcyBldGlxdWV0YXMgZGUgdGV4dG8NCiAgICAgICAgICAgdGwuY29sID0gImJsdWUiLCAgICAgICAgICAjIENvbG9yIGRlIGxhcyBldGlxdWV0YXMgZGUgdGV4dG8NCiAgICAgICAgICAgdGwuc3J0ID0gNDUsICAgICAgICAgICAgICAjIFJvdGFyIGV0aXF1ZXRhcyA0NSBncmFkb3MNCiAgICAgICAgICAgdGl0bGUgPSAiTWF0cml6IGRlIENvcnJlbGFjaW9uZXMiLCANCiAgICAgICAgICAgbWFyID0gYygwLCAwLCAyLCAwKSkgICAgICAjIE3DoXJnZW5lcyBkZWwgZ3LDoWZpY28NCn0NCg0KIyBFamVjdXRhciBhbsOhbGlzaXMgZGUgY29ycmVsYWNpb25lcw0KYW5hbGl6YXJfY29ycmVsYWNpb25lcyhkYXRvc19wcmVwLCBtZXRvZG8gPSAic3BlYXJtYW4iKQ0KDQoNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHBsb3RseSkNCg0KYW5hbGlzaXNfcm9pIDwtIGZ1bmN0aW9uKGRhdG9zKSB7DQogICMgQWdydXBhciB5IGNhbGN1bGFyIG3DqXRyaWNhcw0KICByb2lfcGxvdCA8LSBkYXRvcyAlPiUNCiAgICBncm91cF9ieShjb21wYW55LCBtb250aCkgJT4lDQogICAgc3VtbWFyaXNlKA0KICAgICAgbWFya2V0aW5nX3JvaSA9IG1lYW4obWFya2V0aW5nX3JvaSwgbmEucm0gPSBUUlVFKSwNCiAgICAgIG1hcmtldGluZ19zcGVuZCA9IG1lYW4obWFya2V0aW5nX3NwZW5kLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgLmdyb3VwcyA9ICdkcm9wJyAgIyBFdml0YXIgbWVuc2FqZXMgc29icmUgYWdydXBhbWllbnRvDQogICAgKSAlPiUNCiAgICAjIENyZWFyIGdyw6FmaWNvDQogICAgZ2dwbG90KGFlcyh4ID0gbWFya2V0aW5nX3NwZW5kLCB5ID0gbWFya2V0aW5nX3JvaSwgY29sb3IgPSBjb21wYW55KSkgKw0KICAgIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGFscGhhID0gMC42KSArICAgICAgICMgUHVudG9zIGRlIGRhdG9zDQogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSkgKyAjIEzDrW5lYSBkZSB0ZW5kZW5jaWENCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGxhYnMoDQogICAgICB0aXRsZSA9ICJST0kgdnMgSW52ZXJzacOzbiBlbiBNYXJrZXRpbmciLA0KICAgICAgeCA9ICJJbnZlcnNpw7NuIGVuIE1hcmtldGluZyIsDQogICAgICB5ID0gIlJPSSINCiAgICApICsNCiAgICB0aGVtZSgNCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCAgIyBMZXllbmRhIGVuIGxhIHBhcnRlIGluZmVyaW9yDQogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiwgZmFjZSA9ICJib2xkIiksIA0KICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpDQogICAgKQ0KDQogICMgQ29udmVydGlyIGdyw6FmaWNvIGEgaW50ZXJhY3Rpdm8gY29uIHBsb3RseQ0KICByZXR1cm4oZ2dwbG90bHkocm9pX3Bsb3QpKQ0KfQ0KDQojIFZpc3VhbGl6YXIgYW7DoWxpc2lzIGRlIFJPSQ0KZ3JhZmljb19yb2kgPC0gYW5hbGlzaXNfcm9pKGRhdG9zX3ByZXApDQoNCiMgTW9zdHJhciBncsOhZmljbyBpbnRlcmFjdGl2bw0KZ3JhZmljb19yb2kNCg0KYGBgDQo=